Skip to content

Add V2 region public-key recovery from SHA-384 signatures - #84

Merged
Lash-L merged 1 commit into
mainfrom
research/v2-region-key-recovery
Sep 13, 2026
Merged

Add V2 region public-key recovery from SHA-384 signatures#84
Lash-L merged 1 commit into
mainfrom
research/v2-region-key-recovery

Conversation

@Lash-L

@Lash-L Lash-L commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@Lash-L

Lash-L commented Sep 12, 2026

Copy link
Copy Markdown
Contributor Author

Hello! This is a branch I'm going to use to attempt to get V2 working.

I was able to get this (seemingly) working from a board I sent to @dgiese who was able to do a firmware dump for me with his equipment. My board is still with Dennis so I cannot do the real hardware test myself. It may not work on the first go. Rather than waiting, I'm hoping one of you is able to and we can iterate from there. I'm pinging everyone who has offered to help. (Sorry for the mass ping)

@Flash1232 @fhaala @Kombustor @ppluciennik @181207 @pieterbos @calebsw83 @manukurusu @IIgorrrrr

You can point an agent at this or do it yourself :)

Testing steps for this PR (Docker Compose)

This is an experimental test of the V2 GET /region format . First verify public-key recovery, then check whether the vacuum advances to NC registration and MQTT. Full V2 onboarding has not yet been demonstrated on hardware.

  1. Check out the branch on the server machine.

    For a fresh checkout:

    git clone --branch research/v2-region-key-recovery https://github.com/Python-roborock/local_roborock_server.git
    cd local_roborock_server

    For an existing installation, back up config.toml, data/, and secrets/, then run:

    git fetch origin
    git switch research/v2-region-key-recovery
    git pull --ff-only

    The locally tested commit is 22943d8. Build from this checkout so the running server includes the PR changes.

  2. Configure a fresh installation, or retain the existing configuration.

    For a fresh installation:

    uv sync
    uv run roborock-local-server configure

    Follow the installation guide for DNS and certificates. The api-... hostname must resolve to the server's LAN address. Default ports are HTTPS 555 and MQTT TLS 8881; use the configured ports if they differ.

  3. Build and start the server.

    docker compose up -d --build
    docker compose logs -f roborock-local-server

    Open https://YOUR_API_HOST:555/admin, complete cloud import so the vacuum appears, and enable Allow new app logins, onboarding, and first-time vacuum connections. If custom ports are used, keep the Compose port variables aligned with the configuration as described in the installation guide.

  4. Run terminal onboarding from a second computer with Wi-Fi.

    Check out the same branch on that computer, then run:

    uv run start_onboarding.py --server YOUR_API_HOST:555

    Enter the admin password and Wi-Fi details and select the vacuum. Follow the prompts to perform the model's Wi-Fi reset, join its hotspot, send the onboarding packet, and reconnect the computer to normal Wi-Fi. Use the model-specific Wi-Fi reset procedure; a full factory reset is not needed.

  5. Collect samples and wait for public-key recovery.

    The CLI and dashboard still report Unsupported for V2 in this PR. That status can end CLI polling early while server-side recovery continues. The terminal tool still offers retry for another pairing cycle.

    Leave the server running and allow several minutes for recovery. Check Public Key determined in the admin dashboard, or public_key=True in the CLI status. If the key is still missing, use retry and repeat the pairing cycle. Keep the saved server data between attempts.

    The displayed query sample count can remain zero, because V2 uses header signatures. Recovery requires at least two distinct valid requests; the verified offline capture recovered successfully from three. If several cycles produce no key, collect the results below before doing more retries.

  6. After the key is recovered, run one more pairing cycle.

    Allow approximately five minutes and record the furthest stage reached:

    Observation What it establishes
    Public key recovered V2 key recovery worked
    NC registration appears The vacuum progressed beyond /region
    Authenticated MQTT traffic and status updates Local connectivity is working
    A status request receives a response through the local server The command path works
    The vacuum reconnects after a normal reboot The connection survives a restart

    An HTTP 200 response or a recovered key alone does not prove complete onboarding. The unsupported banner can remain even if later stages work.

  7. Report the result.

    Include the model identifier, firmware version, configured region, Git commit, number of pairing attempts, whether the public key recovered, and the furthest stage reached. Include any TLS or MQTT authentication errors and approximate attempt times.

    Keep these files locally (default Compose paths):

    data/state/device_key_state.json
    data/runtime/decompiled_http.jsonl
    data/runtime/decompiled_mqtt.jsonl
    

    Share redacted excerpts initially. These files can contain credentials and private device information. Preserve the original captures locally so the exact protocol bytes remain available for investigation.

@Flash1232

Copy link
Copy Markdown

Just from a quick initial test:

I've updated my stack (deployed on HA, custom fork repo with this branch) and ran the onboarding again (with your exact branch). So far it again seems to only reach /region as was the case before. Multiple rounds, no query samples. Samples don't increase, pubkey not restored. Do I have to clean some state as I can still see 4 header_samples (presumably from the last attempts)? In that case, I will just clean the decompiled jsonc file. Or am I misunderstanding what to look out for?

Glad to assist with anything if there's need.

@Lash-L

Lash-L commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for testing it out @Flash1232

First thing I would check is that the HA is using the right image/tag. The add-on config points towards an image and I worry it is still using the old code.

After a attempt, does a new entry appear in header_samples in device_key_state.json? Can you send the version, method, path, signature_len, query, nonce, and ts?

As well share the recovery dict in that same file?

@pieterbos

pieterbos commented Sep 13, 2026

Copy link
Copy Markdown

Could you maybe publish the home assistant build for 22943d8 (or later if you updated), and update the tag in the config for the home assistant app/add-on in your branch? It should the be possible to add the custom repository in home assisant, by using https://github.com/Python-roborock/local_roborock_server#<branch_name> , as documented in https://developers.home-assistant.io/docs/apps/presentation/#offering-stable-and-canary-version

I am happy to test, but I need a second computer, and home assistant is the easiest way to accomplish that at the moment for me. Otherwise I have to setup a second Arm single board computer - I have one lying around somewhere, but it'll take longer before I can make time to set that up.

@Lash-L
Lash-L merged commit a917b5e into main Sep 13, 2026
3 checks passed
@Lash-L

Lash-L commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Yes! @pieterbos good idea. I merged this PR and will do the rest later tonight

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants